/*************************************************************/
/*   Headers for a neo-hookean elasticity tensor in MOOSE    */
/*                  Status: not working                      */
/*                                                           */
/* Copyright (C) 2018  eDgar                                 */
/*                                                           */
/* This program is free software: you can redistribute it    */
/* and/or modify it under the terms of the GNU General       */
/* Public License as published by the Free Software          */
/* Foundation, either version 3 of the License, or (at your  */
/* option) any later version.                                */
/*                                                           */
/* This program is distributed in the hope that it will be   */
/* useful, but WITHOUT ANY WARRANTY; without even the        */
/* implied warranty of MERCHANTABILITY or FITNESS FOR A      */
/* PARTICULAR PURPOSE.  See the GNU General Public License   */
/* for more details.                                         */
/*                                                           */
/* You should have received a copy of the GNU General Public */
/* License along with this program.  If not, see             */
/* <http://www.gnu.org/licenses/>.                           */
/*************************************************************/

// Lines like this (starting with //) are extra
// documentation

/* Lines like this are work in progress */

/*
 * Blocks like this are documentation
 */

// With many thanks to Gargi Prasad, Dr. Schwen and the rest
// of moose-users :D !

#ifndef COMPUTEELASTICITYTENSORNEOHOOKEAN_H
#define COMPUTEELASTICITYTENSORNEOHOOKEAN_H

// This declares RankTwoTensor
#include "MooseTypes.h"
// This declares RankFourTensor (to create
// _elasticity_tensor).
#include "RankFourTensor.h"
// Declares the ad (automatic differentiation) property
#include "ADMaterial.h"

// Copy-cat ADComputeStrainBase.h
#define usingNeohookeanElasticityMembers                                \
  usingMaterialMembers;                                                 \
  using ComputeElasticityTensorNeohookean<compute_stage>::_grad_disp

// State what we are creating (with automatic
// differentiation)
template <ComputeStage>
class ComputeElasticityTensorNeohookean;

declareADValidParams(ComputeElasticityTensorNeohookean);

/**
 * ComputeElasticityTensorNeohookean defines an elasticity
 * tensor for the neo-hookean material (referential or
 * Lagrange coordinates)
 *
 *  LaTeX:
 *  {\cal{C}}_{ijkl} = \lambda\,\C_{ij}^{-1}\,\C_{kl}^{-1}
 *                    +\mu\,\left(\C_{ik}^{-1}\,\C_{jl}^{-1}
 *                                +\C_{il}^{-1}*\C_{jk}^{-1}
 *                          \right)
 *
 *  - Belytschko, T., Liu, W. K., Moran, B., & Elkhodary,
 *    K. (2014). Nonlinear finite elements for continua and
 *    structures. : John Wiley and Sons, Ltd.
 *
 *  t4C_ijkl = lambda * C_ij^-1 * C_kl^-1
 *             + mu * (C_ik^-1 * C_jl^-1
 *                     + C_il^-1 * C_jk^-1);
 *
 * */

template <ComputeStage compute_stage>
class ComputeElasticityTensorNeohookean :
  // Inheritance (get declaration of functions, methods and
  // parameters from  other places; inheritance starts after
  // the colon in the declaration of the class)

  // This declares ADMaterialPropertyObject
  public ADMaterial<compute_stage>

{
public:
  // Declare the constructor of this class
  ComputeElasticityTensorNeohookean(const InputParameters & parameters);

protected:
  // Declare variables and methods which are not directly
  // accessible

  // - Qp refers to quadrature points
  //   - This function "Assign{s an} elasticity tensor at a
  //     given given quad point", [see
  //     ComputeElasticityTensor.C, 2017-11-01]
  // - `override' means to make sure that you inherit the
  //   right thing (something that exists)
  virtual void computeQpElasticityTensor();
  /* // TODO */
  /* virtual void computeQpProperties(); */

  /* // Copied from ComputeElasticityTensorBase */
  /* std::string _base_name; */
  /* std::string _elasticity_tensor_name; */

  /* // It is not possible to use the deformation gradient from */
  /* // ADComputeIncrementalStrainBase, because it is defined */
  /* // as a 2nd order identity matrix (the declaration could */
  /* // be reduntant). */
  /* ADMaterialProperty(RankTwoTensor) & _deformation_gradient; */

  void initialSetup() override;
  virtual void displacementIntegrityCheck();

  ///@{ Coupled displacement variable gradients
  const unsigned int _ndisp;
  std::vector<const ADVariableGradient *> _grad_disp;
  ///@}

  // This is the main output of this classs (copy-cat of
  // ComputeElasticityTensorBase). Do not declare before the
  // functions !!
  ADMaterialProperty(RankFourTensor) & _elasticity_tensor;

  usingMaterialMembers;
};

#endif // COMPUTEELASTICITYTENSORNEOHOOKEAN_H
